package com.videoanalysis;

import com.videoanalysis.config.AppConfig;
import lombok.extern.slf4j.Slf4j;
import net.bramp.ffmpeg.FFmpeg;
import net.bramp.ffmpeg.FFmpegExecutor;
import net.bramp.ffmpeg.FFprobe;
import net.bramp.ffmpeg.builder.FFmpegBuilder;
import net.bramp.ffmpeg.probe.FFmpegProbeResult;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 负责从视频中提取关键帧的类
 */
@Slf4j
public class FrameExtractor {
    private final FFmpeg ffmpeg;
    private final FFprobe ffprobe;

    /**
     * 默认构造函数，从配置文件读取FFmpeg路径
     */
    public FrameExtractor() {
        this(AppConfig.getInstance().getFfmpeg().getPath());
    }

    /**
     * 构造函数
     * @param ffmpegPath FFmpeg可执行文件的路径
     */
    public FrameExtractor(String ffmpegPath) {
        try {
            this.ffmpeg = new FFmpeg(ffmpegPath);
            this.ffprobe = new FFprobe(ffmpegPath.replace("ffmpeg", "ffprobe"));
        } catch (IOException e) {
            log.error("初始化FFmpeg失败", e);
            throw new RuntimeException("无法初始化FFmpeg", e);
        }
    }

    /**
     * 从视频中提取关键帧
     * @param videoFile 视频文件
     * @param outputDir 输出目录
     * @return 提取的关键帧文件路径列表
     */
    public List<Path> extractKeyFrames(File videoFile, Path outputDir) throws IOException {
        // 默认每2秒提取一帧
        return extractFrames(videoFile, outputDir, 2);
    }

    /**
     * 从视频中按固定时间间隔提取帧
     * @param videoFile 视频文件
     * @param outputDir 输出目录
     * @param intervalSeconds 提取帧的时间间隔（秒）
     * @return 提取的帧文件路径列表
     */
    public List<Path> extractFrames(File videoFile, Path outputDir, int intervalSeconds) throws IOException {
        log.info("开始从视频提取帧，间隔{}秒: {}", intervalSeconds, videoFile.getName());

        // 确保输出目录存在
        if (!Files.exists(outputDir)) {
            Files.createDirectories(outputDir);
        }

        // 获取视频信息
        FFmpegProbeResult probeResult = ffprobe.probe(videoFile.getAbsolutePath());

        // 构建FFmpeg命令
        FFmpegBuilder builder = new FFmpegBuilder()
                .setInput(videoFile.getAbsolutePath())
                .overrideOutputFiles(true)
                .addOutput(outputDir.resolve("frame_%d.jpg").toString())
                .setFormat("image2")
                .setVideoFilter("fps=1/" + intervalSeconds) // 每intervalSeconds秒提取一帧
                .done();

        // 执行FFmpeg命令
        FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
        executor.createJob(builder).run();

        // 获取生成的帧文件列表
        List<Path> frames = Files.list(outputDir)
                .filter(path -> path.toString().matches(".*frame_\\d+\\.jpg"))
                .sorted()
                .collect(Collectors.toList());

        log.info("成功提取 {} 个关键帧", frames.size());
        return frames;
    }

    /**
     * 获取视频时长（秒）
     * @param videoFile 视频文件
     * @return 视频时长
     */
    public double getVideoDuration(File videoFile) throws IOException {
        FFmpegProbeResult probeResult = ffprobe.probe(videoFile.getAbsolutePath());
        return probeResult.getFormat().duration;
    }

    /**
     * 获取视频基本信息
     * @param videoFile 视频文件
     * @return 视频信息字符串
     */
    public String getVideoInfo(File videoFile) throws IOException {
        FFmpegProbeResult probeResult = ffprobe.probe(videoFile.getAbsolutePath());
        return String.format(
                "文件名: %s\n时长: %.2f秒\n分辨率: %dx%d\n格式: %s\n比特率: %d",
                videoFile.getName(),
                probeResult.getFormat().duration,
                probeResult.getStreams().get(0).width,
                probeResult.getStreams().get(0).height,
                probeResult.getFormat().format_name,
                probeResult.getFormat().bit_rate
        );
    }
}
